import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, LSTM, Dropout, Input
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report, accuracy_score
from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping
import matplotlib.pyplot as plt
import joblib
from sklearn.preprocessing import StandardScaler

# 从 CSV 文件读取数据
data = pd.read_csv("combined_data_new.csv")
data.dropna(axis=0, how='any', inplace=True)

# 输入数据
data_x = data[['sensor1', 'sensor2', 'sensor3', 'sensor4', 'load']].values
# 目标数据
data_y = data['category'].values

# 分割数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(data_x, data_y, test_size=0.2, random_state=42)

# 数据标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# 保存标准化器
joblib.dump(scaler, 'scaler.pkl')

# LSTM 需要 3 维输入，因此调整输入形状
X_train = X_train.reshape((X_train.shape[0], 1, X_train.shape[1]))
X_test = X_test.reshape((X_test.shape[0], 1, X_test.shape[1]))

# 固定超参数
batch_size = 32
rnn_units = 128
dropout_rate = 0.2
epochs = 1

# 构建LSTM模型
model = Sequential([
    Input(shape=(X_train.shape[1], X_train.shape[2])),
    LSTM(rnn_units, return_sequences=True),
    Dropout(dropout_rate),
    LSTM(rnn_units // 2, return_sequences=False),
    Dropout(dropout_rate),
    Dense(1, activation='sigmoid')  # 输出层使用sigmoid激活函数用于二分类
])

# 编译模型
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)  # 固定初始学习率
model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['accuracy'])

# 定义学习率衰减策略和早停
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=3, min_lr=0.0001)
early_stopping = EarlyStopping(monitor='val_loss', patience=5)

# 训练模型
history = model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_split=0.2,
                    callbacks=[reduce_lr, early_stopping], verbose=2)
# 保存模型
model.save('lstm_model.h5')  # 保存为 .h5 文件

# 评估模型
y_pred = (model.predict(X_test) > 0.5).astype("int32")
print("Accuracy:", accuracy_score(y_test, y_pred))
print(classification_report(y_test, y_pred))

# 绘制训练过程的损失和准确率
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Val Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.title('Loss')

plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='Train Accuracy')
plt.plot(history.history['val_accuracy'], label='Val Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.title('Accuracy')

plt.show()
